#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define EXPERIMENTO 9

#define EXECUCOES 1000
#define NUM_GERACOES 100
#define SIZE_MATERIAL 10
#define TCROSS 80
#define TOUR 3

#if EXPERIMENTO == 1
    #define SIZE_POP 100
    #define TMUT 10
#elif EXPERIMENTO == 2
    #define SIZE_POP 50
    #define TMUT 10
#elif EXPERIMENTO == 3
    #define SIZE_POP 200
    #define TMUT 10
#elif EXPERIMENTO == 4
    #define SIZE_POP 100
    #define TMUT 2
#elif EXPERIMENTO == 5
    #define SIZE_POP 100
    #define TMUT 20
#elif EXPERIMENTO == 6
    #undef TOUR
    #define TOUR 2
    #define SIZE_POP 100
    #define TMUT 10
#elif EXPERIMENTO == 7
    #undef TOUR
    #define TOUR 4
    #define SIZE_POP 100
    #define TMUT 10
#elif EXPERIMENTO == 8
    #define SIZE_POP 100
    #define ELITISMO (SIZE_POP*(100-TCROSS)/100)
    #define TMUT 10
#else
    #define SIZE_POP 200
    #define ELITISMO (SIZE_POP*(100-TCROSS)/100)
    #define TMUT 20
    #undef TOUR
    #define TOUR 2
#endif

int seed;

typedef struct indi{
    int sendmory[SIZE_MATERIAL];
    int evaluate;
}INDI, *P_INDI, **DP_INDI;

INDI create_individuo_aleatorio();
INDI create_individuo_aleatorio_metodo_comum();
INDI create_individuo_com_material(int *sendmory);

P_INDI copiar_individuo(P_INDI inicial);
P_INDI create_individuo_aleatorio_ponteiro();

DP_INDI create_population();
DP_INDI copy_population(DP_INDI pop);

int compara_igualdade_individuos(P_INDI indi1, P_INDI indi2);
int compara_avaliacao_individuos_const_void(const void *indi1, const void *indi2);
int populacao_contem_individuo(DP_INDI population, P_INDI indiv, int index);

int *crossover_ciclico(P_INDI indi1, P_INDI indi2);

void mutacao_local_troca(DP_INDI pop);
void imprime_individuo(P_INDI pointer);
void avaliar_individuo(P_INDI pointer);
void torneio(DP_INDI pop, DP_INDI pais);
void copy_population_to_other(DP_INDI p1, DP_INDI p2, int number);

void executa_algoritmo_genetico(DP_INDI populacao, void(*seleciona_pais)(DP_INDI pop, DP_INDI pais), int *(*crossover)(P_INDI indi1, P_INDI indi2),
                                int (*compara_individuos)(const void* indi1, const void* indi2), void (*avaliador)(P_INDI indi), void (*mutacao)(DP_INDI indi));

